﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml;
using DailyBurnSharp.Model;

namespace DailyBurnSharp
{
    public static class XmlParser
    {
        public static User ParseUser(XmlDocument document)
        {
            XmlNode node = document.SelectSingleNode("user");

            var user = new User();
            user.Username = ParseProperty(node, "username");
            user.CurrentWeight = ParseNullableProperty<decimal>(node, "body-weight");
            user.GoalWeight = ParseNullableProperty<decimal>(node, "body-weight-goal");
            user.UsesMetricWeights = ParseProperty<bool>(node, "uses-metric-weights");

            return user;
        }

        public static List<WeightEntry> ParseWeightEntries(XmlDocument document)
        {
            var entries = new List<WeightEntry>();
            
            XmlNodeList nodeList = document.SelectNodes("body-log-entries/body-log-entry");
            if (nodeList == null)
                return entries;

            foreach (XmlNode node in nodeList)
            {
                var entry = new WeightEntry();
                entry.EntryDate = ParseProperty<DateTime>(node, "logged-on");
                entry.Amount = ParseProperty<decimal>(node, "value");
                entry.Units = ParseProperty(node, "unit");

                entries.Add(entry);
            }

            return entries;
        }

        public static List<Food> ParseFoods(XmlDocument document)
        {
            var foods = new List<Food>();

            XmlNodeList nodeList = document.SelectNodes("foods/food");
            if (nodeList == null)
                return foods;

            foreach (XmlNode node in nodeList)
            {
                var food = new Food();
                food.Name = ParseProperty(node, "name");
                food.Brand = ParseProperty(node, "brand");
                food.ServingSize = ParseProperty(node, "serving-size");
                food.Calories = ParseProperty<int>(node, "calories");
                food.FatGrams = ParseProperty<float>(node, "total-fat");
                food.CarbGrams = ParseProperty<float>(node, "total-carbs");
                food.ProteinGrams = ParseProperty<float>(node, "protein");
                food.ThumbnailUrl = ParseProperty(node, "thumb-url");

                foods.Add(food);
            }

            return foods;
        }

        #region XML Helpers

        private static string ParseProperty(XmlNode node, string propertyName)
        {
            if (node != null)
            {
                XmlNode propertyNode = node.SelectSingleNode(propertyName);
                if (propertyNode != null)
                    return propertyNode.InnerText.Trim();
            }

            return String.Empty;
        }

        private static T ParseProperty<T>(XmlNode node, string propertyName) where T : struct
        {
            T result = new T();

            if (node != null)
            {
                XmlNode propertyNode = node.SelectSingleNode(propertyName);
                if (propertyNode != null)
                {
                    TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
                    result = (T)conv.ConvertFrom(propertyNode.InnerText);
                }
            }

            return result;
        }

        private static T? ParseNullableProperty<T>(XmlNode node, string propertyName) where T : struct
        {
            if (node == null)
                return null;

            XmlNode propertyNode = node.SelectSingleNode(propertyName);
            if (propertyNode == null)
                return null;

            string propertyValue = propertyNode.InnerText;
            if (string.IsNullOrEmpty(propertyValue) || propertyValue.Trim().Length == 0)
                return null;

            TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
            return (T)converter.ConvertFrom(propertyValue);
        }

        #endregion // XML Helpers
    }
}